
#include "egl_core.h"

#include "plugin_common.h"
#include "plugin_render.h"
#include "napi/native_api.h"
#include <string>
#include <unistd.h>
#include "camera.h"
#include "stb_image.h"
#include <glm/glm.hpp>

// 获取配置
EGLConfig getConfig(int version, EGLDisplay eglDisplay) {
    int attribList[] = {
        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
        EGL_RED_SIZE, 8,
        EGL_GREEN_SIZE, 8,
        EGL_BLUE_SIZE, 8,
        EGL_ALPHA_SIZE, 8,
        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
        EGL_NONE};
    EGLConfig configs = NULL;
    int numConfigs;
    if (!eglChooseConfig(eglDisplay, attribList, &configs, 1, &numConfigs)) {
        LOGE("eglChooseConfig ERROR");
        return NULL;
    }
    return configs;
}

// 着色器
char vertexShader[] =
    "#version 300 es\n"
    "layout(location = 0) in vec4 a_position;\n"
    "layout(location = 1) in vec4 a_color;\n"
    "out vec4 v_color;\n"
    "void main()\n"
    "{\n"
    "   gl_Position = a_position;\n"
    "   v_color = a_color;\n"
    "}\n";

// 片段着色器
char fragmentShader[] =
    "#version 300 es\n"
    "precision mediump float;\n"
    "in vec4 v_color;\n"
    "uniform vec4 ourColor;\n"
    "out vec4 fragColor;\n"
    "void main()\n"
    "{\n"
    "   fragColor = ourColor;\n"
    "}\n";

// 阴影着色
char shaderfs[] = "#version 300 es\n"
                  "precision mediump float;\n"
                  "out vec4 FragColor; \n"
                  "struct Material { \n"
                  "mpler2D diffuse; \n"
                  "mpler2D specular; \n"
                  "oat shininess; \n"
                  "}; \n"
                  "uniform Material material;\n"

                  "struct Light { \n"
                  "c3 position; \n"
                  "c3 ambient; \n"
                  "c3 diffuse; \n"
                  "c3 specular; \n"
                  "}; \n"
                  "uniform Light light; \n"

                  "uniform vec3 viewPos;\n"
                  "in vec3 Normal;\n"
                  "in vec3 FragPos;\n"
                  "in vec2 TexCoords;\n"
                  "void main() { \n"
                  "c3 ambient = light.ambient * vec3(0.5f,1.0f,0.6f); \n"

                  "c3 norm = normalize(Normal); \n"
                  "c3 lightDir = normalize(light.position - FragPos); \n"
                  "oat diff = max(dot(norm, lightDir), 0.0); \n"
                  "c3 diffuse = light.diffuse * (diff * vec3(0.5f,1.0f,0.6f));\n"
                  "c3 viewDir = normalize(viewPos - FragPos); \n"
                  "c3 reflectDir = reflect(-lightDir, norm); \n"
                  "oat spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); \n"
                  "c3 specular = light.specular * (spec * vec3(0.5f,1.0f,0.6f)); \n"
                  "c3 result = ambient + diffuse + specular; \n"
                  "agColor = vec4(result, 1.0); \n"
                  "}";

// 遮光板
char lightshaderfs[] =
    "#version 300 es\n"
    "precision mediump float;\n"
    "out vec4 FragColor;\n"
    "void main()\n"
    "{\n"
    "   FragColor = vec4(1.0);\n"
    "}\n";

// VS着色
char shadervs[] =
    "#version 300 es\n"
    "layout (location = 0) in vec3 aPos;\n"
    "layout (location = 1) in vec3 aNormal;\n"
    "layout (location = 2) in vec2 aTexCoords;\n"

    "out vec3 Normal;\n"
    "out vec3 FragPos;\n"
    "out vec2 TexCoords;\n"

    "uniform mat4 model;\n"
    "uniform mat4 view; \n"
    "uniform mat4 projection; \n"

    "void main()\n"
    "{\n"
    "TexCoords = aTexCoords;\n"
    "FragPos = vec3(model * vec4(aPos, 1.0));\n"
    "gl_Position = projection*view*model*vec4(aPos, 1.0);\n"
    "Normal = mat3(transpose(inverse(model))) * aNormal; \n"
    "}";

// GL上下文初始化
void EGLCore::GLContextInit(void *window, int w, int h, char *id) {
    LOGE("Zcy EGLCore::GLContextInit window = %{public}p, w = %{public}d, h = %{public}d.", window, w, h);
    width_ = w;
    height_ = h;
    mEglWindow = reinterpret_cast<EGLNativeWindowType>(window);

    mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    if (mEGLDisplay == EGL_NO_DISPLAY) {
        LOGE("Zcy EGLCore::unable to get EGL display.");
        return;
    }
    LOGE("Zcy EGLCore::mEGLDisplay.");
    EGLint eglMajVers, eglMinVers;
    if (!eglInitialize(mEGLDisplay, &eglMajVers, &eglMinVers)) {
        mEGLDisplay = EGL_NO_DISPLAY;
        LOGE("Zcy EGLCore::unable to initialize display");
        return;
    }

    if (eglBindAPI(EGL_OPENGL_ES_API) == EGL_FALSE) {
        LOGE("Zcy Failed to bind OpenGL ES API");
        return;
    }

    LOGE("Zcy EGLCore::getConfig.");
    // 尝试GLES3
    mEGLConfig = getConfig(3, mEGLDisplay);

    if (mEGLConfig == nullptr) {
        LOGE("Zcy EGLCore::GLContextInit config ERROR");
        return;
    }
    LOGE("Zcy EGLCore::getConfig.");

    EGLint surfaceAttributes[] = {
        EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR,
        EGL_NONE};

    if (mEglWindow) {
        LOGE("Zcy EGLCore::eglCreateContext eglSurface from mEglWindow");
        mEGLSurface = eglCreateWindowSurface(mEGLDisplay, mEGLConfig, mEglWindow, surfaceAttributes);
        LOGE("Zcy EGLCore::eglCreateWindowSurface EGL_ERROR = %{public}x, GL_ERROR = %{public}x", eglGetError(), glGetError());
        if (mEGLSurface == nullptr) {
            LOGE("Zcy EGLCore::eglCreateContext eglSurface = null");
            return;
        }
    }

    // 从创建EGL上下文
    int attrib3_list[] = {
        EGL_CONTEXT_CLIENT_VERSION, 2,
        EGL_NONE};

    LOGE("Zcy EGLCore::eglCreateContext");
    mEGLContext = eglCreateContext(mEGLDisplay, mEGLConfig, mSharedEGLContext, attrib3_list);
    LOGE("Zcy EGLCore::eglCreateContext EGL_ERROR = %{public}x, GL_ERROR = %{public}x", eglGetError(), glGetError());
    int error = eglGetError();
    if (error == EGL_SUCCESS) {
        LOGI("EGLCore::Create mEGLContext ok");
    } else {
        LOGE("EGLCore::eglCreateContext error %x", error);
    }
    LOGE("Zcy EGLCore::eglMakeCurrent");
    if (!eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext)) {
        LOGE("EGLCore::eglMakeCurrent error = %d", eglGetError());
    }
    std::string sid{id};
    LOGI("Zcy myids sid = %{public}s", this->id_.c_str());
    if (this->id_.compare("xcomponentId-0")) {
        DrawTransform();
    } else {
        DrawCube();
    }
}

char shadervsTransform[] =
    "#version 300 es\n"
    "layout(location = 0) in vec3 aPos;\n"
    "layout(location = 1) in vec3 aColor;\n"
    "uniform mat4 transform;\n"
    "out vec3 ourColor;\n"
    "void main()\n"
    "{\n"
    "gl_Position = transform * vec4(aPos, 1.0);\n"
    "ourColor = aColor;\n"
    "}\n";

char shaderfsTransform[] =
    "#version 300 es\n"
    "precision mediump float;\n"
    "out vec4 fragColor;\n"
    "in vec3 ourColor;\n"
    "void main()\n"
    "{\n"
    "fragColor = vec4(ourColor, 1.0); \n"
    "}\n";

// 绘图转换
void EGLCore::DrawTransform() {
    float ratio = 0.5;

    float vertices[] = {
        // 位置              // 颜色           // 纹理坐标
        0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.5f,   // 右上
        0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.5f, 0.0f,  // 右下
        -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // 左下
        -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.5f   // 左上
    };

    unsigned int indices[] = {
        0, 1, 3,
        1, 2, 3};

    Shader ourShader(false, shadervsTransform, shaderfsTransform);

    glViewport(0, 0, width_, height_);
    LOGE("Zcy ##DrawWithOpeng 1 failed egl errno : 0x%{public}x, gl errno : 0x%{public}x  ", eglGetError(), glGetError());
    glClearColor(0, 0, 0, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    ourShader.use();

    unsigned int VBO, VAO, EBO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1, &EBO);

    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)0);
    glEnableVertexAttribArray(0);

    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    float stride{10.0};
    while (true) {
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);
        LOGE("zcy DrawTransform");
        stride = stride + 0.05;
        //先旋转再位移
        glm::mat4 trans = glm::mat4(1.0f);
        trans = glm::translate(trans, glm::vec3(0.5f, -0.5f, 0.0f));
        trans = glm::rotate(trans, stride, glm::vec3(0.0f, 0.0f, 1.0f));
        ourShader.use();
        ourShader.setMat4("transform", trans);

        glBindVertexArray(VAO); //必须先绑定VAO，
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
        float timeValue = clock() * 1000 / CLOCKS_PER_SEC;
        float greenValue = sin(timeValue) / 2.0f + 0.5f;
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0 /*&indices*/);

        //画第二个图
        trans = glm::mat4(1.0f);
        trans = glm::translate(trans, glm::vec3(-0.5f, 0.5f, 0.0f));
        float scaleValue = sin(stride);
        trans = glm::scale(trans, glm::vec3(scaleValue, scaleValue, scaleValue));
        ourShader.setMat4("transform", trans);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0 /*&indices*/);

        eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext);
        glFlush();
        //结束
        eglSwapBuffers(mEGLDisplay, mEGLSurface);
        usleep(36660);
    }
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteBuffers(1, &EBO);
    glDeleteProgram(ourShader.ID);
}

const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;

void EGLCore::DrawCube() {
    Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
    float lastX = SCR_WIDTH / 2.0f;
    float lastY = SCR_HEIGHT / 2.0f;
    bool firstMouse = true;

    float deltaTime = 0.0f;
    float lastFrame = 0.0f;

    glEnable(GL_DEPTH_TEST);

    // 构建并编译我们的着色器z程序
    Shader ourShader(false, shadervs, shaderfs);
    Shader lightShader(false, shadervs, lightshaderfs);

    // 位置;法线;纹理坐标
    float vertices[] = {
        -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
        0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f,
        0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f,
        0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f,
        -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f,
        -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,

        -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
        0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f,
        0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
        0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
        -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,
        -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,

        -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
        -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
        -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
        -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
        -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
        -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,

        0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
        0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
        0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
        0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
        0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
        0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,

        -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f,
        0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f,
        0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f,
        0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f,
        -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f,
        -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f,

        -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
        0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,
        0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
        0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
        -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
        -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f};

    glViewport(0, 0, width_, height_);
    LOGE("Zcy ##DrawWithOpeng 1 failed egl errno : 0x%{public}x, gl errno : 0x%{public}x  ", eglGetError(), glGetError());
    glClearColor(0, 0, 0, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glm::vec3 lightPos(1.2f, 1.0f, 2.0f);
    unsigned int VBO, VAO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);

    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    // 位置属性
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)0);
    glEnableVertexAttribArray(0);
    // 法线
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);
    // ST
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)(6 * sizeof(float)));
    glEnableVertexAttribArray(2);

    ourShader.use();
    ourShader.setInt("material.diffuse", 0);
    ourShader.setInt("material.specular", 1);

    float i{10.0};
    while (true) {
        clock_t timestamp = clock() * 1000 / CLOCKS_PER_SEC;
        float currentFrame = static_cast<float>(timestamp);
        deltaTime = currentFrame - lastFrame;
        lastFrame = currentFrame;
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        ourShader.use();

        // 将投影矩阵传递给着色器（请注意，在这种情况下，它可能会更改每一帧）
        glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
        ourShader.setMat4("projection", projection);

        // 摄影机/视图变换
        glm::mat4 view = camera.GetViewMatrix();
        ourShader.setMat4("view", view);

        // 渲染框
        glBindVertexArray(VAO);

        // 计算每个对象的模型矩阵，并在绘制之前将其传递给着色器
        // 确保先将矩阵初始化为单位矩阵
        glm::mat4 model = glm::mat4(1.0f);

        // 光源属性
        ourShader.setVec3("light.ambient", 1.0f, 1.0f, 1.0f);
        ourShader.setVec3("light.diffuse", 1.0f, 1.0f, 1.0f);
        ourShader.setVec3("light.specular", 1.0f, 1.0f, 1.0f);
        // 材料属性
        ourShader.setVec3("material.ambient", 0.0f, 0.1f, 0.06f);
        ourShader.setVec3("material.diffuse", 0.0f, 0.50980392f, 0.50980392f);
        ourShader.setVec3("material.specular", 0.50196078f, 0.50196078f, 0.50196078f);
        ourShader.setFloat("material.shininess", 32.0f);

        i = i + 0.005;
        long t = clock() * 1000 / CLOCKS_PER_SEC;
        lightPos.x = sin(i) * 3.0f;
        lightPos.z = cos(i) * 3.0f;
        LOGE("zcy t: %{public}ld, x: %{public}f, z: %{public}f,", t, lightPos.x, lightPos.z);
        ourShader.setVec3("light.position", lightPos);

        ourShader.setMat4("model", model);

        ourShader.setVec3("viewPos", camera.Position);
        glDrawArrays(GL_TRIANGLES, 0, 36);

        model = glm::mat4(1.0f);
        model = glm::translate(model, lightPos);
        model = glm::scale(model, glm::vec3(0.2f));
        lightShader.use();
        lightShader.setMat4("model", model);
        lightShader.setMat4("projection", projection);
        lightShader.setMat4("view", view);
        glDrawArrays(GL_TRIANGLES, 0, 36);

        eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext);
        glFlush();

        eglSwapBuffers(mEGLDisplay, mEGLSurface);
        usleep(36660);
    }
}